/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package meteocal.entityManager;

import java.util.List;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import meteocal.entity.Event;
import meteocal.entity.Invitation;
import meteocal.entity.Status;
import meteocal.entity.Users;

/**
 *
 * @author andrea
 */
@Stateless
public class InvitationManager {

    @PersistenceContext
    private EntityManager em;
    
    @Inject
    private UserManager um;
    
    /**
     * Saves the invitation in the database.
     * @param invitation
     */
    public void save(Invitation invitation){
        try{
            em.persist(invitation);
        }
        catch(EntityExistsException e){
            Logger.getLogger(InvitationManager.class.getName())
                    .severe("The entity already exists!");
        }
    }
    
    /**
     * Updates the given invitation.
     * @param invitation
     * @throws IllegalArgumentException if the invitation doesn't exist.
     */
    public void update(Invitation invitation){
        if(!exist(invitation)){
            throw new IllegalArgumentException("The invitation doesn't exist");
        } else{
            em.merge(invitation);
        }
    }
    
    /**
     * Removes the invitation from the database.
     * @param invitation
     */
    public void delete(Invitation invitation){
        em.remove(em.merge(invitation));
    }
    
    /**
     * Finds the invitation of the user to the specified event, if exists.
     * @param user
     * @param event
     * @return the invitation
     */
    public Invitation find(Users user, Event event){
        Query query = em.createQuery("SELECT i FROM Invitation i "
                + "WHERE i.event = :event "
                + "AND i.user = :user");
        return (Invitation) query.setParameter("event", event)
                .setParameter("user", user)
                .getSingleResult();
    }
    
    /**
     * Searches all the invitations related to a given user.
     * @param user
     * @return the resulting list (may be null)
     */
    public List<Invitation> findByUser(Users user){
        Query query = em.createQuery("SELECT i FROM Invitation i WHERE i.user = :user");
        try{
            List<Invitation> inviteList = (List<Invitation>) query.setParameter("user", user)
                    .getResultList();
            return inviteList;
        }
        catch(NoResultException e){
            return null;
        }
    }
    
    /**
     * Searches all the pending invitations of the currently logged user.
     * @return the resulting list (may be null)
     */
    public List<Invitation> findByLoggedUser(){
        Query query = em.createQuery("SELECT i FROM Invitation i "
                + "WHERE i.user = :user "
                + "AND i.status = :pending");
        try{
            List<Invitation> inviteList = query.setParameter("user", um.getLoggedUser())
                    .setParameter("pending", Status.PENDING)
                    .getResultList();
            return inviteList;
        }
        catch(NoResultException e){
            return null;
        }
    }
    
     /**
     * Searches all the invitations related to a given event.
     * @param event
     * @return the resulting list (may be null)
     */
    public List<Invitation> findByEvent(Event event){
        Query query = em.createQuery("SELECT i FROM Invitation i WHERE i.event = :event");
        try{
            List<Invitation> inviteList = (List<Invitation>) query.setParameter("event", event)
                    .getResultList();
            return inviteList;
        }
        catch(NoResultException e){
            return null;
        }
    }    

    /**
     * Checks if the given invitation exists in the database.
     * @param invitation
     * @return true if it exists, false otherwise
     */
    private boolean exist(Invitation invitation) {
        Query query = em.createQuery("SELECT i FROM Invitation i WHERE i.event = :event "
                + "AND i.user = :user");
        return (Invitation) query.setParameter("event", invitation.getEvent())
                .setParameter("user", invitation.getUser())
                .getSingleResult() != null;
    }
}
